<?php
class GraphVisualization {

    var $vertex = array();
    var $link = array();
    var $prefix;
    var $tpl_js;

    /**
     * Graph visualization object constructor
     *
     * @param string $type js type (canvas_graph, graph_it)
     * @param array $option name, width, height
     * @param array $vertex
     * @param array $link
     */
    public function __construct(
            $option = array(
                'name' => 'graph',
                'width' => 400,
                'height' => 300
                ),
            $type = 'canvas_graph',
            array $vertex = array(),
            array $link = array()
        ) {
        $this->type = $type;
        $this->link = $link;
        $this->vertex = $vertex;
        $this->option = $option;

        $this->prefix = 'a_';
        $this->tpl_js = '<script  type="text/javascript">%s</script>';
        return true;
    }

    /**
     * Add one new vertex
     *
     * @param int $vertex
     * @param string $name
     * @return bool
     */
    function addVertex($vertex, $name = ''){
        // include not existing wertexes
        $excluded = array();
        foreach($this->vertex AS $tmpWertex){
            $excluded[] = $tmpWertex['vertex'];
        }

        if(!in_array($vertex, $excluded)){
            $this->vertex[] = array('vertex' => $vertex, 'name' => $name);
            return true;
        }
        return false;
    }


    /**
     *
     * @param int $head
     * @param int $tail
     * @param int $type
     * @return bool
     */
    function addLink($head, $tail, $type = 'directed'){
        foreach($this->link AS $link){
            if($link['head'] == $head AND $link['tail'] == $tail){
                return false;
            }
        }

        switch ($type) {
            case 'directed':
                $this->link[] = array('head' => $head, 'tail' => $tail);
                break;
            case 'undirected':
                $this->link[] = array('head' => $head, 'tail' => $tail);
                $this->link[] = array('head' => $tail, 'tail' => $head);
                break;
        }
        return true;
    }

    function addLinks($links, $names = array('start', 'end'))
    {
        foreach($links AS $link){
            $this->addVertex($link[$names[0]], $link[$names[0]]);
            $this->addVertex($link[$names[1]], $link[$names[1]]);
            $this->addLink($link[$names[0]], $link[$names[1]]);
        }
    }

    /**
     *
     * @param string $object
     * @return string
     */
    function getHtmlObjects(){
        $out = null;
        switch ($this->type) {
            case 'canvas_graph':
                $object = '<div %s id="%s">%s</div>';
                foreach($this->vertex AS $vertex){
                    $out .= sprintf($object, '',
                            $this->prefix.$vertex['vertex'],
                            $vertex['name']
                            );
                }
                $out .= '<canvas id="'.$this->option['name'].'" width="'.$this->option['width'].'" height="'.$this->option['height'].'"></canvas>';
                break;

            case 'graph_it':

                $body = '
                    <body onload="initPageObjects();">
                        <div class="canvas" id="mainCanvas"
                            style="width: '.$this->option['width'].'px; height: '.$this->option['height'].'px;
                            border: 1px solid black;">
                            %s
                        </div>
                    </body>';

                // create vertex
                foreach($this->vertex AS $vertex){
                    $out .= '
                        <h2 class="block draggable" id="'.$this->prefix.$vertex['vertex'].'"
                            style="'.
                            'left:'.round(rand(10,$this->option['width']-50)).'px; '.
                            'top:'.round(rand(10,$this->option['height']-20)).'px; '.
                            '">'.
                            $vertex['name'].
                        '</h2>';
                }

                // create links
                foreach($this->link AS $link){
                    $out .= '
                        <div class="connector '.$this->prefix.$link['head'].' '.$this->prefix.$link['tail'].' '.
                            //'down_start '.
                            //'down_end'.
                            '">
                            <img src="library/img/arrow.gif" class="connector-start">'.
                            '<img src="library/img/arrow.gif" class="connector-end">'.
                            //'<label class="source-label">start</label>'.
                            //'<label class="middle-label">middle</label>'.
                            //'<label class="destination-label">end</label>'.
                        '</div>';
                }
                return sprintf($body, $out);
                break;
        }

        return $out;
    }

    function getJs(){
        switch ($this->type) {
            case 'canvas_graph':

                $js = 'var g = new Graph();';
                foreach($this->link AS $link){
                   $js .= 'g.addEdge($("'.$this->prefix.$link['head'].'"), $("'.$this->prefix.$link['tail'].'"));';
                }
                $js .= 'var layouter = new Graph.Layout.Spring(g);';
                $js .= 'layouter.layout();';

                $js .= 'var renderer = new Graph.Renderer.Basic($("'.$this->option['name'].'"), g);';
                $js .= 'renderer.draw();';

                // onload
                //$js .= 'jQuery(document).ready(function(){';
                //$js .= 'var graph = jQuery("#graph").position();';
                //foreach($this->vertex AS $vertex){
                   //$js .= 'jQuery("#'.$this->prefix.$vertex['vertex'].'").css("position", "relative");';
                   //$js .= 'jQuery("#'.$this->prefix.$vertex['vertex'].'").css("top", graph.top+10);';
                   //$js .= 'jQuery("#'.$this->prefix.$vertex['vertex'].'").css("left", graph.left+5);';
                   //$js .= 'var vert = jQuery("#'.$this->prefix.$vertex['vertex'].'").position();';
                   //$js .= 'jQuery("#'.$this->prefix.$vertex['vertex'].'").css("top", 100);';
                   
                //}
                //$js .= '});';

                break;

            case 'graph_it':
                return null;
                break;
        }
        return sprintf($this->tpl_js, $js);
    }

}
?>
